package project.newCode;

import java.io.*;
import java.util.*;

import project.hulpPakket.*;
import project.newCode.surfaces.Box;
import project.newCode.surfaces.IndexedTriangleSet;

public class ObjParser {


	public static void main(String[] args) {
		ObjParser n = new ObjParser();
		n.parse("/Users/roel/Downloads/obj/guitar.obj.txt");
	}
	private int numfaces = 0;
	private int numtextures = 0;
	private int numnormals = 0;
	private int numvertices = 0;
	public ObjParser() {
		// TODO Auto-generated constructor stub
	}
	public IndexedTriangleSet parse(String filename){
		BufferedReader in = null;
		try {
			in = new BufferedReader(new FileReader(filename));
		} catch (FileNotFoundException e) {
			e.fillInStackTrace();
			//System.out.println(e);
			System.exit(0);
		}

		Vector<Point3f> coordinates = new Vector<Point3f>();
		Vector<Vector3f> normals = new Vector<Vector3f>();
		Vector<TexCoord2f> textureCoordinates = new Vector<TexCoord2f>();
		Vector<Integer> coordinateIndices = new Vector<Integer>();
		Vector<Integer> textureCoordinateIndices = new Vector<Integer>();
		Vector<Integer> normalIndices = new Vector<Integer>();

		numfaces = 0;
		numtextures = 0;
		numnormals = 0;
		numvertices = 0;
		Point3f boxMin = new Point3f(Float.MAX_VALUE,Float.MAX_VALUE,Float.MAX_VALUE);
		Point3f boxMax = new Point3f(Float.MIN_VALUE,Float.MIN_VALUE,Float.MIN_VALUE);

		String nextLine = null;

		try {
			nextLine = in.readLine();
		} catch (IOException e) {
			e.fillInStackTrace();
			//System.out.println(e);
			System.exit(0);
		}

		while(nextLine != null){
			if(!nextLine.trim().isEmpty()){
				StringTokenizer tokenizer = new StringTokenizer(nextLine);
				String nextToken = tokenizer.nextToken();

				if(nextToken.equals("#")){
					//Comment -> Ignore this line
				}
				else if(nextToken.equals("g")){
					//Group token -> ignore
				}
				else if(nextToken.equals("mtllib")){
					// Material token _> Ignore (for now)
				}
				else if(nextToken.equals("usemtl")){
					//Ignore
				}
				else if(nextToken.equals("s")){
					//Ignore
				}
				else if(nextToken.equals("v")){
					numvertices++;
					Point3f p = new Point3f(Float.parseFloat(tokenizer.nextToken()),Float.parseFloat(tokenizer.nextToken()),Float.parseFloat(tokenizer.nextToken()));
					coordinates.add(p);
					if(p.x < boxMin.x) boxMin.x = p.x;
					if(p.y < boxMin.y) boxMin.y = p.y;
					if(p.z < boxMin.z) boxMin.z = p.z;
					if(p.x > boxMax.x) boxMax.x = p.x;
					if(p.y > boxMax.y) boxMax.y = p.y;
					if(p.z > boxMax.z) boxMax.z = p.z;

				}
				else if(nextToken.equals("vn")){
					numnormals++;
					normals.add(new Vector3f(Float.parseFloat(tokenizer.nextToken()),Float.parseFloat(tokenizer.nextToken()),Float.parseFloat(tokenizer.nextToken())).normalise());
				}
				else if(nextToken.equals("vt")){
					numtextures++;
					textureCoordinates.add(new TexCoord2f(Float.parseFloat(tokenizer.nextToken()),Float.parseFloat(tokenizer.nextToken())));
				}
				else if(nextToken.equals("f")){//Next line is specifies a face.  Parse face. Not only triangles! Polygons are subdivided into triangles!
					int numtokens=tokenizer.countTokens();
					numfaces = numfaces+numtokens-2;
					String[] indices;
//					int firstc = 0;
//					int firstn = 0;
//					int firstt = 0;
					for(int i=0; i<numtokens; i++) {
						// split token
						indices = tokenizer.nextToken("[ \\]").split("/");
						coordinateIndices.add((int) Float.parseFloat(indices[0]));
						try {
							textureCoordinateIndices.add((int) Float.parseFloat(indices[1]));
						} 
						catch (Exception e) {
						}
						try {
							normalIndices.add((int) Float.parseFloat(indices[2]));
						} catch (Exception e) {
						}

//						if (i<3) {//first triangle
//							coordinateIndices.add((int) Float.parseFloat(indices[0]));
//							try {
//								textureCoordinateIndices.add((int) Float.parseFloat(indices[1]));
//								normalIndices.add((int) Float.parseFloat(indices[2]));
//							} 
//							catch (Exception e) {
//							}
//							if(i==0){
//								firstc = coordinateIndices.get(coordinateIndices.size()-1);
//								try {
//									firstn = normalIndices.get(normalIndices.size()-1);
//									firstt = textureCoordinateIndices.get(textureCoordinateIndices.size()-1);
//								} catch (Exception e) {
//									// TODO Auto-generated catch block
//									e.printStackTrace();
//								}
//							}
//						}
//						else {//Subsequent triangle, take first point and previous two points
//							coordinateIndices.add(firstc);
//							coordinateIndices.add(coordinateIndices.get(coordinateIndices.size()-3));
//							coordinateIndices.add((int) Float.parseFloat(indices[0]));
//							try {
//								textureCoordinateIndices.add(firstt);
//								textureCoordinateIndices.add(textureCoordinateIndices.get(textureCoordinateIndices.size()-3));
//								textureCoordinateIndices.add((int) Float.parseFloat(indices[1]));
//								normalIndices.add(firstn);
//								normalIndices.add(normalIndices.get(normalIndices.size()-3));
//								normalIndices.add((int) Float.parseFloat(indices[2]));
//							} 
//							catch (Exception e) {
//							}
//						}
					}
				}
				else if(nextToken.matches("[0-9]*")){
					// Face cont'd
					tokenizer = new StringTokenizer(nextLine);
					int numtokens=tokenizer.countTokens();
					numfaces = numfaces+numtokens;
					String[] indices;
					for(int i=0; i<numtokens; i++) {
						indices = tokenizer.nextToken("[ \\]").split("/");
						//Subsequent triangle, take new point and previous two points
						coordinateIndices.add(coordinateIndices.get(coordinateIndices.size()-1));
						coordinateIndices.add(coordinateIndices.get(coordinateIndices.size()-3));
						coordinateIndices.add((int) Float.parseFloat(indices[0]));
						try {
							textureCoordinateIndices.add(textureCoordinateIndices.get(textureCoordinateIndices.size()-1));
							textureCoordinateIndices.add(textureCoordinateIndices.get(textureCoordinateIndices.size()-3));
							textureCoordinateIndices.add((int) Float.parseFloat(indices[1]));
							normalIndices.add(normalIndices.get(normalIndices.size()-1));
							normalIndices.add(normalIndices.get(normalIndices.size()-3));
							normalIndices.add((int) Float.parseFloat(indices[2]));
						} 
						catch (Exception e) {
						}
					}


				}
			}
			try {//Get next line
				nextLine = in.readLine();
			} catch (IOException e) {
				e.fillInStackTrace();
				//System.out.println(e);
				System.exit(0);
			}//Finished Getting next line
		}//Finished parsing
		// Copy elements into arrays for efficiency

//		System.out.println(coordinates.size()+" "+coordinates.toString());
//		System.out.println(normals.size()+" "+normals.toString());
//		System.out.println(textureCoordinates.size()+" "+textureCoordinates.toString());
//		System.out.println(coordinateIndices.size()+" "+coordinateIndices.toString());
//		System.out.println(normalIndices.size()+normalIndices.toString());
//		System.out.println(textureCoordinateIndices.size()+" "+textureCoordinateIndices.toString());
		System.out.println(boxMin+" "+boxMax);
		Point3f[] cv = new Point3f[numvertices];
		coordinates.toArray(cv);
		Vector3f[] nv = new Vector3f[numnormals];
		normals.toArray(nv);
		TexCoord2f[] tv = new TexCoord2f[numtextures];
		textureCoordinates.toArray(tv);
		int [] ci = new int[numfaces*3];
		int [] ni = new int[numfaces*3];
		int [] ti = new int[textureCoordinateIndices.size()];
		System.out.println(numfaces);
		for(int i = 0; i<numfaces*3; i++) {
			ci[i] = coordinateIndices.get(i);
			if(normalIndices.size()>0){
				ni[i] = normalIndices.get(i);
			}
			if(textureCoordinateIndices.size()>0){
				ti[i] = textureCoordinateIndices.get(i);
			}
		}
		return new IndexedTriangleSet(cv,nv,tv,ci,ni,ti,numfaces,new Box(boxMin,boxMax),null);


	}
}
